iT邦幫忙

2024 iThome 鐵人賽

DAY 8
0
Software Development

一個好的系統之好維護基本篇 ( 馬克版 )系列 第 8

Day-08: 實務時 Code Review 看的地方之 1 ( 基本 )

  • 分享至 

  • xImage
  •  

同步至 medium

接下來來的幾篇文章,應該會比較注重在實務時,我 code review 時,會觀看的一些重點,其中性能方面的東西我會跳過,但這不代表不會看,只是因為這次的主題都是維護性,性能有興趣的可以去看之前這個系統。

30–30 之馬克版的一個好的系統攻略本 — 性能基礎篇

然後接下來要說的比較專注在這個層級。

https://ithelp.ithome.com.tw/upload/images/20240922/20089358lIkTBlL6wn.png


看點 1. 是否符合軟體需求

我覺得這個是最基本的,但是有時後連我寫出來的東西都和需求是兩件事,我先說一下我自已在這裡的看點是 :

  1. 測試案例。
  2. 看 Figma 或 PRD 來看看這個 API 有沒有符合前端的需求。
  3. 看看 PR Description。

然後我自已說說我的發現的一些事情。

首先看測試案例的方向,我自已覺得是沒什麼問題。但實際上我覺得有幾個問題 :

  1. 大部份測案都是工程師開發時看 PRD 與 Figma 來自已想的測試案例,和 QA 與 PM 想的測案是兩件事,所以事實上只要需求理解有問題,那事實上這個測案就是沒用的東西,所以這時通常我反而會先看 PRD 或 Figma 然後再來想測案合不合理,但是這個真的很耗費時間。
  2. 有些 User Story 有 AC,但是有時後工程在開 task 票時,有時後就會想說這個 API 可以連其它 story 的一些功能先做,因為一起做比較快,所以就變成 task 要完成的與 user story 的 AC 沒有相同,導致有時後會沒注意到。
  3. 雖然 User Story 有 AC,但很情況下因為 user story 都是根據 figma 的畫面來切分,所以 AC 實際上是以畫面的角度在撰寫,然後實際需要什麼欄位實際上都還是去 figma 自已看。

我們自已也有發現這個問題,所以目前有在進行幾個嘗試 :

  1. QA 的測試案例先行。
  2. Example Mapping。

QA 測試案例先行我自已是覺得有幫助不少,可以讓我在想測案時,比較不需要憑空變出來。

在來是 example mapping,他之後會開一篇講講,簡單來說他的概念就是 :

找幾個人,然後根據這個 user story 用 example 來更理解需求,然後通常 exmaple 就可以當 AC.

但我那時試了一次後發現目前還有點不太適合在我們團隊中,原因如下 :

  1. 我們的 user story 都是以 ui base 來開,所以他們都覺得就去看 figma 就好。
  2. 每個 user story 的範圍有點不確定,例如有個 user story 是查看某個列表,但是後來發現列表內的搜尋與排序放在其它 user story 中,所以變成每個人要知道整個 user story 的關聯性才比較好知道範圍。
  3. 太花時間。

雖然我目前碰到這些問題導致有點難用 example mapping,但我自已是覺得他很適合用來讓團隊共同理解需求產 user story 基本 AC的方法 ~ 之後在寫一篇來討論這個東西。


看點 2. Function 的 Variable 的 Naming

第一個就把工程第一難題拿出來說說,我自已主要會看以下的東西 :

  1. 命名我是否看的懂,如果我看不懂,然後你看的懂,接下來我會找第三個幫我看一下,如果他也看的懂,那就是我英文的問題…
  2. 命名所衍伸的範圍。
  3. 命名規範是否符合團隊。
  4. 命名符合實作,不要 getCourse 裡面多了,會計算觀看課程次數。
  5. 如果是 domain model 通常會用 event storming 或越接近業務面越好。

然後下面說個幾點我覺得比較需要談談的。

2. 命名所衍伸的範圍

再來是第 2 點就比較需要討論一下,例如以下的兩種命名 :

  • getCourses
  • getPublishedCourse

然後如果我們這次的需求是需要取到已發佈的課程那會選那個呢 ? 這題事實上是個大齋問呢 ? 公說公有理,婆說婆有理。

選擇 getCourses 派的理由基本上有以下,簡單的說就是為了擴展性 :

  • 這樣未來如果要在取得,例如草稿課程,那就不用在改了。
  • getCourses 內本身就算是 getPublishedCourse 就算現在只回傳 published,也算合理,而且之後擴展時還不用改。

選擇 getPublishedCourse 派的理由基本上有以下,簡單的說為了維護性 :

  • SRP 原則,可以降低使用的 Context 這樣,如果之後要修改時,就不會動到他。
  • 現在沒有用其它的情境要使用,有可能做了 getCourses 後,未來仍然還是只抓 published 的。
  • getCourses 使用範圍太大,接下來所有抓 getCourses 都會用它,它只會一直變大。

這題如果我的話,我年輕時會選 1,但我現在會先選 2 再選 1 。

年輕時我總是很喜歡抽象,然後做出一個很通用的東西,然後總是想未來很多使用情境。但是最後幾年後,我自已後來回去看時,都發現我自已都看不懂了,而且裡面多了一堆 if else,然後別人改了裡面,外面用的地方炸的機率很高,因為年輕時總是預想了很多不存在的情境。

然後現在的話,我會先選 2,接下來如果在碰到需求,才會開始考慮重構,因為我知道情境了,然後慢慢讓他支援的情境慢慢變大,並且還會考慮它所在的層級與方法定位來決定要做到多通用。

不要預先設計可以支援太多還不確定的情境的方法

題外思考 :

那如果是 DB Schema 或是 API 設計呢 ? 你會選擇設計 product schema 還是 course schema ? 然後接下來是 API 呢 ?

5.如果是 domain model 通常會用 event storming 或越接近業務面越好

domain model 不熟的朋朋可以先跳過之後會說,但如果熟的應該知道我在說什麼。

就是我們有個 course domain model,然後實務上我們有個是更新募資時間的方法,但這時就有兩種方法名的設計 :

  1. updateIncubatingTime
  2. update

有人會選第 2 個是因為,他就只是一個欄位的更新,有需要開一個方法嗎 ? 直接寫在 udpate 裡不就好了 ? 但這裡我們只要是 domain model 就會根據 event storming 討論出的 command 來命名,就算只是真的針對一個欄位進行更新也是。

主要的原因在於是讓 domain model 越接近業務越好,因為這樣越好維護,而且如果有營運的人來問你說,我們更新募資的條件是什麼,還是我們系統有支援那些更新,那這樣只要看 domain model 就可以知道。


看點 3. Function 的 Parameter

  1. 會不會太長 ? 如果不是 create 類的 ? 你為啥參數為啥會長成這樣 ?
  2. 有 1 個 flag (selector arguments) 還可以接受,那如果有 2 個 flag 可能就要想一下為啥了 ?

第 1 點整體來說會影響到以下幾個點 :

  • 可讀性差 : 會讓其它使用這個方法的人,要花很多時間才能理解這個方法與的作用。
  • 易於出錯:使用方法時容易混淆參數的順序,特別是當多個參數類型相似或相同時,可能會導致錯誤。
  • 維護困難 : 隨著業務需求的變更,可能需要經常增加或移除參數,這會使得函數的維護變得更複雜。

然後通常太長的 Parameter 有可能是以下幾個點產生 :

  • 做太多事情,就是包山包海
  • 做太少事情,就是所有的東西都需要外面進來。

然後通常如果能拆就拆吧,如果不能就建議用 object,至少在使用時會方便不少。

然後第 2 點,flag 事實上就代表 1 個使用情境,通常 1 個我還可以接受,但如果是 2 個可能就會先問一下為什麼了。

然後順到寫個,使用 parameter object 可以增加可讀性的感覺,就是如下程式碼,事實上第 2 種很明顯就知道每個參數的意思 ? 然後有些語而本來就有支援 named argument,但在 ts 目前好像也只能這樣寫 (偽 named argument。

// Bad
sendMessage("hello", 1, true)
// Good 
sendMessage({
  message: "hello",
  prioority: 1,
  allowRetry: true
})

看點 4. 是否放對位置

這個東西事實上取決於 :

你設計這個方法是為了什麼 ?

通常最開始這個設計出來的用意就是只支援這個 class 內的,就是我們常說的 private 的方法,這個通常問題不大。

但比較需要討論的是這個,除了給原本的用,但覺得它很通用,所以想放在某個通用的地方給其它人用,這個我自已覺得本意算不錯,只是重點在於它是否通用?

通常只有幾個條件,我才會覺得可以放到通用的地方 :

  • 實務上本來就很通用的東西,例如時間、金額、一些基礎建設元件。
  • 使用情境是很全世界都是一樣的,例如 http 請求 client 之類的。

但是業務上的通用,建議先停看聽,很多情況下,那個通用是可能是平台、工程師自已覺得、這個情境下的通用,之前就有發生過,有個平台要取得到可發佈的課程資訊,但沒想到可發佈每個平台都是不一樣的。

這種業務上的通用,建議除非是 event storming 後,所有人認可的,那不然就等等,因為『 你的通用不是每個人的通用 』。


看點 5. 是否符合團隊風格

就通常每個團隊可能都有不同的使用與命名的一些風格,建議新到一個地方先四處看看 code 或最新的 pr,最好的話有文件會比較好,但如果是 legacy 很久的地方,建議看最新的 pr 比較好。

然後主要大概會是以下幾點 :

  • 命名規範
  • 程式結構與使用的語法
  • 註解
  • 錯誤處理

正常情況下,很多東西都可以用一些工具來自動化來自動完成 ( eslint ),但有些時後還是只能團隊要想辦法有共同的遵守原則。

小心得:
但我覺得最難的就是要如何維護那個 rule,和讓每個人都記得住。


小結

這篇文章中我大概整理了一下我 code review 時會看的幾個點,然後接下來還有幾篇還會繼續討論其中的,明眼人應該還知道缺了很多 :

  • 看點 1. 是否符合軟體需求
  • 看點 2. Function 的 Variable 的 Naming
  • 看點 3. Function 的 Parameter
  • 看點 4. 是否放對位置
  • 看點 5. 是否符合團隊 Code convention

上一篇
Day-07: 設計原則的小整理
下一篇
Day-09: 實務時 Code Review 看的地方之 2 ( 好理解 )
系列文
一個好的系統之好維護基本篇 ( 馬克版 )30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
Sunny.Cat
iT邦新手 3 級 ‧ 2024-09-22 22:49:33

非常認同!!/images/emoticon/emoticon32.gif

我要留言

立即登入留言